/**
 * Copyright 2012 Inomera Research
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.netmera.mobile;

import java.io.IOException;
import java.util.List;

import v2.simpleUi.M_Button;
import v2.simpleUi.M_Caption;
import v2.simpleUi.M_Checkbox;
import v2.simpleUi.M_Container;
import v2.simpleUi.M_Container2;
import v2.simpleUi.M_InfoText;
import v2.simpleUi.SimpleUI;
import v2.simpleUi.util.IO;
import v3.M_TextModifier;
import v3.maps.GeoUtils;
import v3.maps.GoogleMapsV2View;
import v3.maps.GoogleMapsV2View.MarkerListener;
import v3.maps.GoogleMapsV2View.Overlay;
import v3.maps.I_MapView;
import v3.maps.M_GoogleMapsV2;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Toast;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;

public class NetmeraMobileStarterActivity extends FragmentActivity {
	private static final String FILENAME_USER_SAVE = "userSave";
	private static final String LOC = "location";
	private static final String USER_CONTENT = "Usercontent";
	private static final int MIN_LOCATION_ACCURACY = 40;
	private static final int MAX_RETRIES = 10;
	protected static final String LOG_TAG = "NetmeraMobileStarterActivity";
	private NetmeraUser loggedInUser;
	private NetmeraContent userContent;
	protected boolean updatePositionOnServer = true;
	protected int otherUserIcon = com.netmera.mobile.R.drawable.ic_launcher;
	protected Overlay otherUsersOverlay;
	protected LatLng userPos;
	protected String channel = "Droidcon2013";

	public void setLoggedInUser(NetmeraUser loggedInUser, String pw) {
		this.loggedInUser = loggedInUser;
		if (channel != null) {
			storeOnDevice(new UserSaveObject(loggedInUser.getEmail(), pw,
					channel));
		}
	}

	public void storeOnDevice(UserSaveObject us) {
		try {
			IO.saveSerializableToPrivateStorage(this, FILENAME_USER_SAVE, us);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void tryToLoadLoggedInUser() {
		try {
			UserSaveObject f = loadUserFile();
			if (f == null) {
				return;
			}
			channel = f.getChannel();
			NetmeraUser.loginInBackground(f.getEmail(), f.getPw(),
					new NetmeraCallback<NetmeraUser>() {

						@Override
						public void callback(NetmeraUser u, NetmeraException e) {
							if (e != null) {
								e.printStackTrace();
							} else if (u != null) {
								loggedInUser = u;
								loadUserContentFromServer(loggedInUser, aboutYourselfTextString,
										MAX_RETRIES);
							}
						}
					});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public UserSaveObject loadUserFile() {
		try {
			UserSaveObject f = (UserSaveObject) IO
					.loadSerializableFromPrivateStorage(this,
							FILENAME_USER_SAVE);
			return f;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		String API_KEY = "WVhCd1ZYSnNQV2gwZEhBbE0wRWxNa1lsTWtZeE16WTVNekEzTXk1dVpYUnRaWEpoTG1OdmJTVXpRVGd3SlRKR2JXOWlhVzFsY21FbE1rWm5ZV1JuWlhRbE1rWjBkWFJ2Y21saGJDNTRiV3dtYm0xVGFYUmxWWEpzUFdoMGRIQWxNMEVsTWtZbE1rWXhNelk1TXpBM015NXVaWFJ0WlhKaExtTnZiU1V6UVRnd0ptMXZaSFZzWlVsa1BURTVOVE0zSm1Gd2NFbGtQVEV6Tmprek1EY3pKbTV0VkdWdGNHeGhkR1U5Ylc5aWFYUmxiWEJzWVhSbEptOTNibVZ5U1dROWMybHRiMjR0YUdWcGJtVnVKbVJ2YldGcGJqMXVaWFJ0WlhKaExtTnZiU1p1YlZOcGRHVTlNVE0yT1RNd056TW1iM2R1WlhKU2IyeGxWSGx3WlQweEpuWnBaWGRsY2xKdmJHVlVlWEJsUFRFbWRtbGxkMlZ5U1dROWMybHRiMjR0YUdWcGJtVnVKZw==";
		NetmeraClient.init(NetmeraMobileStarterActivity.this, API_KEY);

		tryToLoadLoggedInUser();

		M_Container2 c = new M_Container2();

		c.add(new M_Caption("Droidcon People Finder"));

		addInstructionsUi(c);

		addLoginUi(c);

		addChannelEditorUi(c);

		c.add(new M_Checkbox() {
			@Override
			public void onCheckedChanged(Context context, CheckBox e,
					boolean isChecked) {
				updatePositionOnServer = isChecked;
				super.onCheckedChanged(context, e, isChecked);
			}

			@Override
			public boolean save(boolean newValue) {
				return true;
			}

			@Override
			public boolean loadVar() {
				return updatePositionOnServer;
			}

			@Override
			public CharSequence getVarName() {
				return "Update my position for others";
			}
		});

		// manuallRefreshButton(c);

		c.add(new M_GoogleMapsV2() {

			@Override
			public void onNewAreaOnMapIsShown(LatLng topLeft,
					LatLng bottomRight, int zoomLevel) {

				try {
					if (channelNotCorrectlySet(channel, false)) {
						return;
					}
					NetmeraGeoLocation a = new NetmeraGeoLocation(
							topLeft.latitude, topLeft.longitude);
					NetmeraGeoLocation b = new NetmeraGeoLocation(
							bottomRight.latitude, bottomRight.longitude);
					NetmeraService q = new NetmeraService(USER_CONTENT);
					q.whereEqual("channel", channel);
					q.boxSearchInBackground(b, a, LOC,
							getOtherPeopleResultListener());
				} catch (NetmeraException e) {
					e.printStackTrace();
				}
			}

			@Override
			public void onDevicePosUpdate(Activity activity, I_MapView mapView,
					LatLng pos, Location posAsLocation, boolean firstUpdate) {
				if (firstUpdate) {
					mapView.setMapCenterTo(pos, 19);
				}
				if (posAsLocation.getAccuracy() < MIN_LOCATION_ACCURACY) {
					onUserMoved(pos);
				}
				userPos = pos;
			}

			@Override
			public void onMapViewIsReadyForTheFirstTime(
					GoogleMapsV2View googleMapsV2View,
					FragmentActivity activity, GoogleMap mapController) {
				GoogleMapsV2View.initDefaultBehavior(googleMapsV2View);
				otherUsersOverlay = googleMapsV2View
						.addNewEmptyOverlay(otherUserIcon);
			}

			@Override
			public int getMapHeigthInDip() {
				return 400;
			}
		});

		setContentView(c.getView(this));

	}

	private void addInstructionsUi(M_Container2 c) {
		c.add(new M_Button("Instructions") {

			@Override
			public void onClick(Context context, Button clickedButton) {
				SimpleUI.showInfoDialog(context, "Ok", new M_Instructions());
			}
		});
	}

	public void addLoginUi(M_Container2 c) {

		c.add(new M_Button("Current user..") {

			@Override
			public void onClick(Context context, Button clickedButton) {

				M_Container c = new M_Container();
				c.add(new M_Caption("User Manager"));
				String ut = "No user logged in";
				if (loggedInUser != null) {
					ut = loggedInUser.getNickname();
				}
				c.add(new M_InfoText("Current user:", ut));
				if (loggedInUser != null) {
					c.add(new M_InfoText("Email:", loggedInUser.getEmail()));
				}
				M_Button login = new M_Button("Login") {

					@Override
					public void onClick(Context context, Button clickedButton) {
						showLoginWindow(context);
					}
				};
				c.add(login);
				M_Button register = new M_Button("Register as a new user") {

					@Override
					public void onClick(Context context, Button clickedButton) {
						showRegistrationWindow(context);
					}

				};
				c.add(register);
				SimpleUI.showInfoDialog(context, "Close", c);
			}
		});

	}

	private void updateChannelInStorage(String channel) {
		UserSaveObject f = loadUserFile();
		if (f != null) {
			f.setChannel(channel);
			storeOnDevice(f);
		}
	}

	public void addChannelEditorUi(M_Container2 c) {
		c.add(new M_Button("Current channel..") {

			@Override
			public void onClick(Context context, Button clickedButton) {
				M_Container c = new M_Container();
				c.add(new M_TextModifier() {

					@Override
					public boolean save(String newValue) {
						if (channelNotCorrectlySet(newValue, true)) {
							return false;
						}
						channel = newValue;
						updateChannelInStorage(channel);
						return true;
					}

					@Override
					public String load() {
						return channel;
					}

					@Override
					public String getVarName() {
						return "Channel";
					}
				});
				SimpleUI.showCancelOkDialog(context, "Cancel", "Ok", c);
			}
		});
	}
String aboutYourselfTextString;
	public void showRegistrationWindow(Context context) {
		if (channelNotCorrectlySet(channel, true)) {
			return;
		}
		SimpleUI.showCancelOkDialog(context, "Cancel", "Ok",
				new M_RegisterForm() {
					@Override
					public void onUserLoggedIn(NetmeraUser u, String pw,
							String aboutYourselfText) {
						loggedInUser = null;
						userContent = null;
						aboutYourselfTextString=aboutYourselfText;
						setLoggedInUser(u, pw);
						loadUserContentFromServer(u, aboutYourselfText, 0);
					}

				});
	}

	public NetmeraCallback<List<NetmeraContent>> getOtherPeopleResultListener() {
		return new NetmeraCallback<List<NetmeraContent>>() {

			@Override
			public void callback(List<NetmeraContent> otherUsers,
					NetmeraException e) {
				if (e != null) {
					e.printStackTrace();
					// showMessageToUser("Error while loading other users");
				} else {
					try {
						onOtherUsersAroundMeReceived(otherUsersOverlay,
								otherUsers);
					} catch (NetmeraException e1) {
						e1.printStackTrace();
						// showMessageToUser("Error while loading other users");
					}
				}
			}

		};
	}

	private void onOtherUsersAroundMeReceived(Overlay otherUsersOverlay,
			List<NetmeraContent> otherUsers) throws NetmeraException {
		Log.i(LOG_TAG, "Found " + otherUsers.size() + " usercontents around me");
		otherUsersOverlay.clear();
		for (NetmeraContent u : otherUsers) {
			final NetmeraContent userContent = u;
			NetmeraGeoLocation loc = userContent.getNetmeraGeoLocation(LOC);
			LatLng pos = new LatLng(loc.getLatitude(), loc.getLongitude());
			try
			{otherUsersOverlay.add(pos, false, new MarkerListener() {

				@Override
				public boolean onTab(Marker marker) {
					showInfoWindowForUser(NetmeraMobileStarterActivity.this,
							userContent);
					return false;
				}

				@Override
				public void onDragEvent(Marker marker, int eventType) {
				}
			});
			}
			catch(Exception e){
				e.printStackTrace();
			}
			
		}
	}

	protected void showInfoWindowForUser(Activity activity,
			NetmeraContent userContent) {
		try {
			SimpleUI.showInfoDialog(activity, "Close",
					new M_UserContentInfoView(activity, userContent));
		} catch (NetmeraException e) {
			e.printStackTrace();
		}
	}

	private void loadUserContentFromServer(final NetmeraUser u,
			final String aboutYourselfText, final int retryCounter) {
		userContent = null;
		if (channelNotCorrectlySet(channel, true)) {
			return;
		}
		NetmeraService service = new NetmeraService(USER_CONTENT);
		/*
		 * TODO Netmera bug, no users found when filtering for email or
		 * channel..
		 */
		service.whereEqual("email", u.getEmail());
		// service.whereEqual("channel", channel);
		try {
			service.whereOwnerEqual(u);
		} catch (NetmeraException e1) {
			e1.printStackTrace();
		}
		service.searchInBackground(new NetmeraCallback<List<NetmeraContent>>() {

			@Override
			public void callback(List<NetmeraContent> results,
					NetmeraException searchError) {
				if (searchError != null) {
					searchError.printStackTrace();
					if (retryCounter < MAX_RETRIES) {
						loadUserContentFromServer(u, aboutYourselfText,
								retryCounter + 1);
					} else {
						showMessageToUser("No connection to server");
						return;
					}
				}
				if (results != null) {
					if (results.size() == 0) {
						try {
							Log.i(LOG_TAG, "After " + retryCounter
									+ " retries: No user "
									+ "content found yet so creating"
									+ " a new one");
							createNewUserContentFor(u, aboutYourselfText, 0);
							return;
						} catch (NetmeraException e) {
							e.printStackTrace();
						}
					} else {
						onUserContentsFoundOnServer(u, results);
						return;
					}
				}
			}
		});
	}

	private boolean channelNotCorrectlySet(String c, boolean showUserMessage) {
		boolean r = c == null || c.length() < 5;
		if (r) {
			showMessageToUser("First enter a channel (more then 4 characters)");
		}
		return r;
	}

	protected void showMessageToUser(String string) {
		try {
			Toast.makeText(this, string, Toast.LENGTH_LONG).show();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	protected void createNewUserContentFor(final NetmeraUser u,
			final String aboutYourselfText, final int retryCounter)
			throws NetmeraException {
		Log.i(LOG_TAG, "Creating new user content object");
		NetmeraContent content = new NetmeraContent(USER_CONTENT);
		content.add("email", u.getEmail());
		content.add("nickname", u.getNickname());
		content.add("channel", channel);
		if (aboutYourselfText!=null)content.add("about", aboutYourselfText);
		try {
			Location loc = new GeoUtils(this).getLastKnownPosition();
			content.add(
					LOC,
					new NetmeraGeoLocation(loc.getLatitude(), loc
							.getLongitude()));
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		content.createInBackground(new NetmeraCallback<NetmeraContent>() {

			@Override
			public void callback(NetmeraContent c, NetmeraException e) {
				if (e != null) {
					e.printStackTrace();
					if (retryCounter < MAX_RETRIES) {
						try {
							createNewUserContentFor(u, aboutYourselfText,
									retryCounter + 1);
						} catch (NetmeraException e1) {
							e1.printStackTrace();
						}
					} else {
						showMessageToUser("Could not create new user correctly!");
						return;
					}
				} else {
					Log.i(LOG_TAG, "Created user content: " + c.data);
					userContent = c;
				}
			}
		});
	}

	protected void onUserMoved(LatLng pos) {
		if (updatePositionOnServer && loggedInUser != null) {
			try {
				NetmeraContent content = userContent;
				if (content == null) {
					Log.e(LOG_TAG, "No userContent object received jet");
					return;
				}
				content.add(LOC, new NetmeraGeoLocation(pos.latitude,
						pos.longitude));
				content.add("channel", channel);
				System.out.println("Trying to update person "
						+ userContent.getString("email"));
				content.updateInBackground(new NetmeraCallback<NetmeraContent>() {

					@Override
					public void callback(NetmeraContent c, NetmeraException e) {
						if (e != null) {
							e.printStackTrace();
						} else {
							System.out.println("Should have worked: " + c.data);
						}
					}
				});
			} catch (NetmeraException e) {
				e.printStackTrace();
			}
		}
	}

	public void showLoginWindow(Context context) {
		if (channelNotCorrectlySet(channel, true)) {
			return;
		}
		SimpleUI.showCancelOkDialog(context, "Cancel", "Ok", new M_LoginForm() {

			@Override
			public void onUserLoggedIn(NetmeraUser u, String pw) {
				setLoggedInUser(u, pw);
				loadUserContentFromServer(u, aboutYourselfTextString, MAX_RETRIES);
			}

		});
	}

	public void onUserContentsFoundOnServer(final NetmeraUser u,
			List<NetmeraContent> results) {
		Log.i(LOG_TAG, "Found existing user content object");

		for (NetmeraContent uc : results) {
			try {
				if (uc.getString("channel").equals(channel)) {
					userContent = uc;
					break;
				}
			} catch (NetmeraException e) {
				e.printStackTrace();
			}
		}
		if (userContent == null) {
			userContent = results.get(0);
		}

		showMessageToUser("User " + u.getNickname() + " logged in successfully");
	}
}
